home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
pctjoc85.arc
/
FATFISH.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-08-07
|
14KB
|
532 lines
{ WA-TOR program -- Inspired by Scientific American, 12/84 }
{$debug+} {1}
{$entry+} {1}
{$line+} {1}
PROGRAM wator(input,output) ;
{ pascal library functions }
FUNCTION umulok(a,b:word ; VAR c:word) : boolean ; {4}
EXTERN ; {4}
FUNCTION tics : word ; {6}
EXTERN ; {6}
{ assembly language utilities }
PROCEDURE set_cursor(row,column: integer) ;
EXTERN ;
PROCEDURE clear_screen ;
EXTERN ;
PROCEDURE install_break_handler ;
EXTERN ;
FUNCTION check_break : boolean ;
EXTERN ;
PROCEDURE remove_break_handler ;
EXTERN ;
CONST
{ describe the size of the wator world }
xsize = 79 ; { horizontal size of wator }
maxx = 78 ; { xsize -1 }
ysize = 20 ; { vertical size of wator }
maxy = 19 ; { ysize -1 }
TYPE
{ describe the fish lists used to keep track of wator's beings }
species = (fish,shark,empty) ;
xcoord = 0..maxx ;
ycoord = 0..maxy ;
link = ^fishes ; {5}
fishes = RECORD
next : link ;
prev : link ;
kind : species ;
age : integer ;
x : xcoord ;
y : ycoord ;
ate : integer ;
END ;
{ identify the neighbors of a given fish or shark }
neighbor = RECORD
x : integer ;
y : integer ;
kind : species ;
END ;
neighborhood = ARRAY [1..8] OF neighbor ;
VAR
{ heads and tails of the lists of beings on wator }
fish_head : link ;
fish_tail : link ;
shark_head : link ;
shark_tail : link ;
{ array to identify what is currently at a place in wator }
pond : ARRAY [xcoord,ycoord] OF species ;
{ variables that describe the characteristics of wator }
nfishes : integer ; { init number of fishes in pond }
nsharks : integer ; { init number of sharks in pond }
sbreed : integer ; { chronons btwn shark breeding }
fbreed : integer ; { chronons btwn fish breeding }
starve : integer ; { time a shark can go w/o eating }
{ miscellaneous variables }
generation : integer ;
counts : ARRAY [fish..shark] OF integer ;
neighbors : ARRAY [1..4] OF neighbor ;
abort : boolean;
seed : word ;
{ utility function to implement universe wrapping }
FUNCTION wrap(c,l:integer) : integer ;
BEGIN
c := c MOD l ;
IF c < 0 THEN
c := c + l ;
wrap := c ;
END ;
{ random number generator }
FUNCTION random(max_index:integer) : integer ;
VAR
overflow : boolean ;
BEGIN
overflow := umulok(15625,seed,seed) ; {4}
random := trunc(max_index*(abs(float(ord(seed)))/32768.0)) ; {4}
END ;
{ procedure to display a fish (or water) at a given location }
PROCEDURE display_fish(x:xcoord ;
y:ycoord ;
t:species) ;
BEGIN
set_cursor(y,x) ; {3}
IF t = fish THEN
BEGIN
write(','); {3}
END
ELSE IF t = shark THEN
BEGIN
write('δ'); {3}
END
ELSE
write(' '); {3}
pond[x,y] := t ;
END ;
{ procedure to add a new fish (or shark) to the pond }
PROCEDURE add_fish(p:link ;
p_kind:species ;
p_x:xcoord ;
p_y:ycoord) ;
VAR
t : link ;
BEGIN
new(t) ; {5}
counts[p_kind] := counts[p_kind] + 1 ;
WITH t^ DO
BEGIN
next := p^.next ;
prev := p ;
kind := p_kind ;
age := 0 ;
x := p_x ;
y := p_y ;
ate := 0 ;
display_fish(p_x,p_y,p_kind) ;
END ;
p^.next^.prev := t ;
p^.next := t ;
END ;
{ procedure to delete an entry from a fish list }
PROCEDURE delete_fish(p:link) ;
BEGIN
WITH p^ DO
BEGIN
counts[p^.kind] := counts[p^.kind] - 1 ;
prev^.next := next ;
next^.prev := prev ;
display_fish(x,y,empty) ;
dispose(p) ;
END ;
END ;
{ procedure to check the pond around a given fish/shark }
PROCEDURE check_pond(p_x:xcoord ;
p_y:ycoord ;
t:species ;
VAR n:integer ;
VAR a:neighborhood) ;
VAR
tx : xcoord ;
ty : ycoord ;
i : integer ;
BEGIN
n := 0 ;
FOR i := 1 TO 4 DO
BEGIN
tx := wrap(p_x+neighbors[i].x,xsize) ;
ty := wrap(p_y+neighbors[i].y,ysize) ;
IF pond[tx,ty] = t THEN
BEGIN
n := n + 1 ;
WITH a[n] DO
BEGIN
x := tx ;
y := ty ;
kind := pond[tx,ty] ;
END ;
END ;
END ;
END ;
{ procedure to make fish swim }
PROCEDURE fish_swim ;
VAR
f_link : link ;
f_n : integer ;
f_nghbr : neighborhood ;
old_x : xcoord ;
old_y : ycoord ;
r : integer ;
BEGIN
f_link := fish_head^.next ;
WHILE (f_link <> fish_tail) DO
WITH f_link^ DO
BEGIN
IF check_break THEN
BEGIN
abort := true ;
break ;
END;
check_pond(x,y,empty,f_n,f_nghbr) ;
IF f_n > 0 THEN
BEGIN
old_x := x ;
old_y := y ;
r := random(f_n) + 1 ;
display_fish(x,y,empty) ;
x := f_nghbr[r].x ;
y := f_nghbr[r].y ;
display_fish(x,y,fish) ;
IF age >= fbreed THEN
BEGIN
add_fish(fish_head,fish,old_x,old_y) ;
age := 0 ;
END
ELSE
age := age + 1 ;
END
ELSE
age := age + 1 ;
f_link := next ;
END ;
END ;
{ procedure where a fish turns into a shark nummy }
PROCEDURE eat_fish(p_x:xcoord ;
p_y:ycoord) ;
VAR
f_link : link ;
eaten : boolean ;
BEGIN
eaten := false ;
f_link := fish_head^.next ;
WHILE (f_link<>fish_tail) AND ( NOT eaten) DO
WITH f_link^ DO
IF (x = p_x) AND (y = p_y) THEN
BEGIN
delete_fish(f_link) ;
f_link := NIL ;
eaten := true ;
END
ELSE
f_link := next ;
END ;
{ shark hunt and breeding procedure }
PROCEDURE shark_move ;
LABEL
next_shark ;
VAR
s_link : link ;
s_n : integer ;
s_nghbr : neighborhood ;
old_x : xcoord ;
old_y : ycoord ;
r : integer ;
BEGIN
s_link := shark_head^.next ;
WHILE (s_link <> shark_tail) DO
WITH s_link^ DO
BEGIN
IF check_break THEN
BEGIN
abort := true;
break;
END;
{ feeding section }
check_pond(x,y,fish,s_n,s_nghbr) ;
IF s_n > 0 THEN
BEGIN
old_x := x ;
old_y := y ;
r := random(s_n) + 1 ;
display_fish(x,y,empty) ;
x := s_nghbr[r].x ;
y := s_nghbr[r].y ;
eat_fish(x,y) ;
display_fish(x,y,shark) ;
ate := 0 ;
IF age >= sbreed THEN
BEGIN
add_fish(shark_head,shark,old_x,old_y) ;
age := 0 ;
END
ELSE
age := age + 1 ;
s_link := next ;
GOTO next_shark ;
END ;
{ starvation section }
ate := ate + 1 ;
IF ate > starve THEN
BEGIN
set_cursor(ysize+4,40) ;
write
('shark at position (',y:2,',',x:2,') starved...') ;
s_link := next ;
delete_fish(s_link^.prev) ;
GOTO next_shark ;
END ;
{ move to unoccupied section }
check_pond(x,y,empty,s_n,s_nghbr) ;
IF s_n > 0 THEN
BEGIN
old_x := x ;
old_y := y ;
r := random(s_n) + 1 ;
display_fish(x,y,empty) ;
x := s_nghbr[r].x ;
y := s_nghbr[r].y ;
display_fish(x,y,shark) ;
IF age >= sbreed THEN
BEGIN
add_fish(shark_head,shark,old_x,old_y) ;
age := 0 ;
END
ELSE
age := age + 1 ;
s_link := next ;
GOTO next_shark ;
END ;
{ if we get here, the shark just gets older }
age := age + 1 ;
s_link := next ;
GOTO next_shark ;
next_shark:
END ;
END ;
{ initialization procedure }
PROCEDURE init ;
VAR
i : integer ;
tx : xcoord ;
ty : ycoord ;
tt : boolean ;
BEGIN
clear_screen ;
set_cursor(0,0) ;
writeln('Welcome to WA-TOR.') ;
writeln('How many fishes does WA-TOR have?') ;
writeln('Pick a number between 1..1000. Try 200.') ;
read(i) ;
IF (i>1000) OR (i<1) THEN
nfishes := 200
ELSE
nfishes := i ;
writeln('How many sharks does WA-TOR have?') ;
writeln('Pick a number between 1..200. Try 20.') ;
read(i) ;
IF (i>200) OR (i<1) THEN
nsharks := 20
ELSE
nsharks := i ;
writeln('How often do the fish breed?') ;
writeln('Pick a between 1..100 chronons. Try 3 chronons.') ;
read(i) ;
IF (i>100) OR (i<1) THEN
fbreed := 3
ELSE
fbreed := i ;
writeln('How often do the sharks breed?') ;
writeln('Pick a between 1..100 chronons. Try 10 chronons.') ;
read(i) ;
IF (i>100) OR (i<1) THEN
sbreed := 10
ELSE
sbreed := i ;
writeln('How long can a shark go without eating?') ;
writeln('Pick a between 1..100 chronons. Try 3 chronons.') ;
read(i) ;
IF (i>100) OR (i<1) THEN
starve := 3
ELSE
starve := i ;
clear_screen;
set_cursor(ysize+1,40) ;
write('fish breed every ',fbreed:3,' chronons') ;
set_cursor(ysize+2,40) ;
write('sharks breed every ',sbreed:3,' chronons') ;
set_cursor(ysize+3,40) ;
write('sharks starve after ',starve:3,' chronons') ;
set_cursor(ysize+4,0) ;
write('Press Ctrl-Break to end WA-TOR...') ;
abort := false;
seed := tics ;
neighbors[1].x := 0 ;
neighbors[1].y := - 1 ;
neighbors[2].x := - 1 ;
neighbors[2].y := 0 ;
neighbors[3].x := 1 ;
neighbors[3].y := 0 ;
neighbors[4].x := 0 ;
neighbors[4].y := 1 ;
new(fish_head) ;
new(fish_tail) ;
new(shark_head) ;
new(shark_tail) ;
fish_head^.next := fish_tail ;
fish_head^.prev := NIL ;
fish_tail^.next := NIL ;
fish_tail^.prev := fish_head ;
shark_head^.next := shark_tail ;
shark_head^.prev := NIL ;
shark_tail^.next := NIL ;
shark_tail^.prev := shark_head ;
counts[fish] := 0 ;
counts[shark] := 0 ;
generation := 1 ;
FOR tx := 0 TO maxx DO
FOR ty := 0 TO maxy DO
pond[tx,ty] := empty ;
FOR i := 1 TO nfishes DO
BEGIN
tt := true ;
WHILE tt DO
BEGIN
tx := random(xsize) ;
ty := random(ysize) ;
IF pond[tx,ty] = empty THEN
BEGIN
add_fish(fish_head,fish,tx,ty) ;
fish_head^.next^.age := random(fbreed) ;
tt := false ;
END ;
END ;
END ;
FOR i := 1 TO nsharks DO
BEGIN
tt := true ;
WHILE tt DO
BEGIN
tx := random(xsize) ;
ty := random(ysize) ;
IF pond[tx,ty] = empty THEN
BEGIN
add_fish(shark_head,shark,tx,ty) ;
WITH shark_head^.next^ DO
BEGIN
age := random(sbreed) ;
ate := random(starve) ;
END ;
tt := false ;
END ;
END ;
END ;
END ;
{ main program }
BEGIN
init ;
install_break_handler ;
WHILE ((fish_head^.next <> fish_tail) OR
(shark_head^.next <> shark_tail)) AND
(NOT abort) DO
BEGIN
set_cursor(ysize+1,0) ;
write('fishes = ',counts[fish]:4) ;
set_cursor(ysize+2,0) ;
write('sharks = ',counts[shark]:4) ;
set_cursor(ysize+3,0) ;
write('generation = ',generation:4) ;
fish_swim ;
shark_move ;
generation := generation + 1 ;
END;
clear_screen ;
set_cursor(0,0) ;
IF (fish_head^.next = fish_tail) AND
(shark_head^.next = shark_tail) THEN
writeln('All life on WA-TOR extinct...') ;
remove_break_handler ;
END.